package com.edu.internship.util;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

/**
 * code is far away from bug with the animal protecting
 *
 * @author lsq28657638@gmail.com
 * @description 编码工具类
 * @date Create in 2017/12/19 11:13
 */
public class EncodeUtils {

    /**
     * CBC 填充方式
     */
    private static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding";
    /**
     * 默认密钥
     */
    private static final String KEY = "1q2w3e4r5t6y7u8i";
    /**
     * 偏移量
     */
    private static final String IV = "1234567812345678";

    private EncodeUtils() {
    }

    /**
     * MD5加密
     *
     * @param input 输入
     * @return String
     */
    public static String encodeMd5(String input) {
        return DigestUtils.md5Hex(input);
    }

    /**
     * MD5加密
     *
     * @param input 输入
     * @param salt  盐值
     * @return String
     */
    public static String encodeMd5(String input, String salt) {
        return DigestUtils.md5Hex(input + salt);
    }

    /**
     * Base64编码
     *
     * @param input 输入
     * @return String
     */
    public static String encodeBase64(byte[] input) {
        return new String(Base64.encodeBase64(input));
    }

    /**
     * Base64编码
     *
     * @param input 输入
     * @return String
     */
    public static String encodeBase64(String input) {
        try {
            return new String(Base64.encodeBase64(input.getBytes(StandardCharsets.UTF_8.name())));
        } catch (UnsupportedEncodingException e) {
            return StringUtils.EMPTY;
        }
    }

    /**
     * Base64解码
     *
     * @param input    输入
     * @param isDecode 是否编过码
     * @return byte[]
     */
    public static byte[] decodeBase64(String input, boolean isDecode) {
        if (isDecode) {
            return Base64.decodeBase64(input);
        } else {
            return Base64.decodeBase64(input.getBytes());
        }
    }

    /**
     * Base64解码
     *
     * @param input    输入
     * @param isDecode 是否编过码
     * @return String
     */
    public static String decodeBase64String(String input, boolean isDecode) {
        try {
            return new String(decodeBase64(input, isDecode), StandardCharsets.UTF_8.name());
        } catch (UnsupportedEncodingException e) {
            return StringUtils.EMPTY;
        }
    }

    /**
     * Html转码
     *
     * @param html html
     * @return String
     */
    public static String escapeHtml(String html) {
        return StringEscapeUtils.escapeHtml4(html);
    }

    /**
     * Html解码
     *
     * @param htmlEscaped 转义过的html
     * @return String
     */
    public static String unEscapeHtml(String htmlEscaped) {
        return StringEscapeUtils.unescapeHtml4(htmlEscaped);
    }

    /**
     * Xml转码
     *
     * @param xml xml
     * @return String
     */
    public static String escapeXml(String xml) {
        return StringEscapeUtils.escapeXml10(xml);
    }

    /**
     * Xml解码
     *
     * @param xmlEscaped 转义过的xml
     * @return String
     */
    public static String unEscapeXml(String xmlEscaped) {
        return StringEscapeUtils.unescapeXml(xmlEscaped);
    }

    /**
     * URL编码, Encode默认为UTF-8
     *
     * @param part part
     * @return String
     */
    public static String encodeUrl(String part) {
        return encodeUrl(part, StandardCharsets.UTF_8.name());
    }

    /**
     * URL解码, Encode默认为UTF-8
     *
     * @param part part
     * @return String
     */
    public static String decodeUrl(String part) {
        return decodeUrl(part, StandardCharsets.UTF_8.name());
    }

    /**
     * URL编码, Encode自定义
     *
     * @param part     String
     * @param encoding 编码
     * @return String
     */
    public static String encodeUrl(String part, String encoding) {
        try {
            return new URLCodec().encode(part, encoding);
        } catch (UnsupportedEncodingException e) {
            return StringUtils.EMPTY;
        }
    }

    /**
     * URL解码, Encode自定义
     *
     * @param part     part
     * @param encoding 编码
     * @return String
     */
    public static String decodeUrl(String part, String encoding) {
        try {
            return new URLCodec().decode(part, encoding);
        } catch (DecoderException | UnsupportedEncodingException e) {
            return StringUtils.EMPTY;
        }
    }

    /**
     * 使用默认密钥加密
     *
     * @param content 原文
     * @return 密文
     */
    public static String encodeAes(String content) {
        return encodeAes(KEY, content);
    }

    /**
     * 加密
     *
     * @param strKey  密钥
     * @param content 原文
     * @return 密文
     */
    public static String encodeAes(String strKey, String content) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
            cipher.init(Cipher.ENCRYPT_MODE,
                    new SecretKeySpec(strKey.getBytes(StandardCharsets.UTF_8), "AES"),
                    new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8))
            );
            byte[] encryptedByteArr = cipher.doFinal(content.getBytes());
            return encodeBase64(encryptedByteArr);
        } catch (Exception e) {
            return StringUtils.EMPTY;
        }
    }

    /**
     * 使用默认密钥解密
     *
     * @param content 密文
     * @return 原文
     */
    public static String decodeAes(String content) {
        return decodeAes(KEY, content);
    }

    /**
     * 解密
     *
     * @param strKey  密钥
     * @param content 密文
     * @return 原文
     */
    public static String decodeAes(String strKey, String content) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
            cipher.init(Cipher.DECRYPT_MODE,
                    new SecretKeySpec(strKey.getBytes(StandardCharsets.UTF_8), "AES"),
                    new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8))
            );
            byte[] encryptedByteArr = decodeBase64(content, false);
            byte[] original = cipher.doFinal(encryptedByteArr);
            return new String(original, StandardCharsets.UTF_8);
        } catch (Exception e) {
            return StringUtils.EMPTY;
        }
    }
}
